package org.linuxsogood.boot.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

/**
 * @author liu.hongwei
 */
public class NioServer {


    public static void main(String[] args) throws IOException {

        // 得到serverSocketChannel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        // 得到一个Selector
        Selector selector = Selector.open();

        // 绑定一个端口6666, 在服务器端监听
        serverSocketChannel.socket().bind(new InetSocketAddress(6666));

        // 设置为非阻塞
        serverSocketChannel.configureBlocking(false);

        // 将ServerSocketChannel 注册到selector, 关注OP_ACCEPT事件
        SelectionKey selectionKey = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        // 循环等侍客户端连接
        while (true) {
            if (selector.select(1000) == 0) {
                // 没有事件发生
                System.out.println("server wait one sec, no event.");
                continue;
            }

            // 获取到关注的事件集合, 拿到集合遍历
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey nextSelectionKey = iterator.next();

                ByteBuffer buffer = ByteBuffer.allocate(1024);
                if (nextSelectionKey.isAcceptable()) {
                    System.out.println("客户端已连接");
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ, buffer);
                }

                if (nextSelectionKey.isReadable()) {
                    SocketChannel channel = (SocketChannel) nextSelectionKey.channel();
                    channel.read(buffer);
                    System.out.println("client message: " + new String(buffer.array()));
                }
                // 手动从集合中移除当前的selectionKey, 避免重复
                iterator.remove();
            }

        }

    }

}
